<?php


namespace app\controller;
use app\BaseController;
use think\Request;
use think\Response;
use think\facade\Db;
use app\model\AdvertModel;
use app\validate\AdvertValidate;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use think\facade\Filesystem;
use app\common\Snowflake;
use think\facade\Request as FileRequest;
use PhpOffice\PhpSpreadsheet\IOFactory;

class Advert extends BaseController {

    private function jsonResponse(int $code, string $msg, $data = []): Response
    {
        return json(compact('code', 'msg', 'data'));
    }


    // 新增广告
    public function create()
    {

        $data = $this->request->post();

        validate(AdvertValidate::class)->check($data);

        $snowflake = new Snowflake(1, 1);
        $data['ad_id'] = $snowflake->nextId();

        $ad = AdvertModel::create($data);

        return $this->jsonResponse(0, 'success', $ad->id);
    }

    // 列表分页
    public function list()
    {
        $page = $this->request->param('page/d', 1);
        $limit = $this->request->param('limit/d', 10);
        $isShow = $this->request->param('is_show/d', -1);
        $adId = $this->request->param('ad_id');

        $query = AdvertModel::withSearch(['is_show', 'ad_id'], [
            'is_show' => $isShow > -1 ? $isShow : null,
            'ad_id' => $adId
        ]);

        $list = $query->paginate(['page' => $page, 'list_rows' => $limit])
            ->toArray();

        return $this->jsonResponse(0, 'success', $list);
    }

    // 编辑广告
    public function update($id)
    {
        $data =  $this->request->post();

        validate(AdvertValidate::class)->check($data);

        $result = AdvertModel::update($data, ['id' => $id]);

        if ($result) {
            return json(['code' => 0, 'msg' => '更新成功']);
        } else {
            return json(['code' => 1, 'msg' => '更新失败']);
        }
    }

    // 删除广告
    public function delete($id)
    {
        $advert = AdvertModel::findOrFail($id);
        $advert->delete();
        return $this->jsonResponse(0, '删除成功');
    }

    // 导出数据
    public function export()
    {
        $isShow = $this->request->param('is_show/d', -1);
        $adId = $this->request->param('ad_id');

        $query = AdvertModel::withSearch(['is_show', 'ad_id'], [
            'is_show' => $isShow > -1 ? $isShow : null,
            'ad_id' => $adId
        ]);

        $list = $query->select()->toArray();

        // 创建一个新的 Spreadsheet 对象
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // 设置表头
        $sheet->setCellValue('A1', 'ID');
        $sheet->setCellValue('B1', '图片URL');
        $sheet->setCellValue('C1', '是否跳转');
        $sheet->setCellValue('D1', '是否展示');
        $sheet->setCellValue('E1', '排序');
        $sheet->setCellValue('F1', '修改时间');

        // 填充数据
        $row = 2;
        foreach ($list as $item) {
            $sheet->setCellValue('A' . $row, $item['id']);
            $sheet->setCellValue('B' . $row, $item['file_url']);
            $sheet->setCellValue('C' . $row, $item['jump_type']);
            $sheet->setCellValue('D' . $row, $item['is_show']);
            $sheet->setCellValue('E' . $row, $item['sort']);
            $sheet->setCellValue('F' . $row, $item['update_time']);
            $row++;
        }

        // 输出 Excel 文件
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="advert_export.xlsx"');
        header('Cache-Control: max-age=0');

        $writer = new Xlsx($spreadsheet);
        $writer->save('php://output');
    }


    // 导入数据
    public function import()
    {
        // 获取上传文件
        $file = FileRequest::file('file');
        if (!$file) {
            return json(['code' => 1, 'msg' => '请选择要上传的文件', 'data' => []]);
        }

        // 验证文件格式
        $allowExt = ['csv', 'xlsx', 'xls'];
        $ext = $file->getOriginalExtension();
        if (!in_array($ext, $allowExt)) {
            return json(['code' => 1, 'msg' => '仅支持CSV/Excel文件', 'data' => []]);
        }

        // 移动文件到临时目录
        $savePath = runtime_path() . 'import/';
        if (!is_dir($savePath)) {
            mkdir($savePath, 0755, true);
        }
        $filename = uniqid() . '.' . $ext; // 避免文件名冲突
        $file->move($savePath, $filename);
        $filePath = $savePath . $filename;

        try {
            // 读取文件内容
            $spreadsheet = IOFactory::load($filePath);
            $sheet = $spreadsheet->getActiveSheet();
            $rows = $sheet->toArray(); // 原始数据（可能包含null）

            // === 修复：全局替换null为空字符串 ===
            $rows = array_map(function ($row) {
                return array_map(fn ($v) => $v === null ? '' : $v, $row); // 核心修复
            }, $rows);

            $success = 0;
            $errors = [];
            $snowflake = new Snowflake(1, 1);

            // 校验表头
            $header = array_map('trim', $rows[0]);
            $requiredHeaders = ['ID', '图片URL', '是否跳转', '是否展示', '排序', '修改时间'];
            foreach ($requiredHeaders as $h) {
                if (!in_array($h, $header)) {
                    throw new \Exception("缺少必要表头：{$h}");
                }
            }

            // 从第二行开始处理
            for ($rowNum = 1; $rowNum < count($rows); $rowNum++) {
                $row = $rows[$rowNum]; // 已处理null为''
                if (empty(array_filter($row))) {
                    $errors[] = ['row' => $rowNum + 1, 'msg' => '数据为空行'];
                    continue;
                }

                // 按正确列顺序解析数据（使用?? ''确保非null）
                $data = [
                    'id' => $row[0] ?? '',
                    'file_url' => $row[1] ?? '',
                    'jump_type' => $row[2] ?? '',
                    'is_show' => $row[3] ?? '',
                    'sort' => $row[4] ?? 0,
                    'update_time' => $row[5] ?? '',
                ];

                // === 数据转换 ===
                // 1. 生成ad_id
                if (empty($data['id'])) {
                    $data['id'] = $snowflake->nextId();
                }

                // 2. 是否跳转转换
                $data['jump_type'] = match ($data['jump_type']) {
                    '是', '1' => 1,
                    default => 0,
                };

                // 3. 是否展示转换
                $data['is_show'] = match ($data['is_show']) {
                    '是', '1' => 1,
                    default => 0,
                };

                // === 数据验证 ===
                $validate = new \think\Validate([
                    'file_url' => 'require|url',
                    'jump_type' => 'in:0,1',
                    'is_show' => 'in:0,1',
                    'sort' => 'integer|between:0,999',
                ]);

                if (!$validate->check($data)) {
                    $errors[] = [
                        'row' => $rowNum + 1,
                        'msg' => $validate->getError()
                    ];
                    continue;
                }

                // === 唯一性校验 ===
                if (AdvertModel::where('id', $data['id'])->find()) {
                    $errors[] = [
                        'row' => $rowNum + 1,
                        'msg' => "广告ID已存在：{$data['id']}"
                    ];
                    continue;
                }

                // === 写入数据库 ===
                try {
                    AdvertModel::create($data);
                    $success++;
                } catch (\Exception $e) {
                    $errors[] = [
                        'row' => $rowNum + 1,
                        'msg' => "数据库错误：{$e->getMessage()}"
                    ];
                }
            }

            // 删除临时文件
            @unlink($filePath);

            return json([
                'code' => 0,
                'msg' => "导入完成，成功{$success}条，失败" . count($errors) . "条",
                'data' => [
                    'success' => $success,
                    'errors' => $errors
                ]
            ]);

        } catch (\Exception $e) {
            @unlink($filePath);
            return json([
                'code' => 1,
                'msg' => "导入失败：{$e->getMessage()}",
                'data' => []
            ]);
        }
    }
}
